﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Imageo.bintje;
using System.Web.UI.HtmlControls;
using System.Runtime.Serialization;
using System.Net;
using System.Threading;
using System.Drawing;
using log4net;
using System.Collections.Specialized;

namespace Imageo.ui
{
    public partial class TrailDetails : System.Web.UI.Page
    {
        private static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

        int trailId;
        bool CanEdit;
        bool EditMode;
        bool EasyMode;
        bintje.fullTrail currentTrail;
        bintje.imageoSession currentSession = null;
        ServiceAPI service;
        int proUserId = 0;

        protected void Page_Load(object sender, EventArgs e)
        {
            currentSession = Session["BintjeSession"] as imageoSession;

            string strProUserId = Request.QueryString["prouserid"] as string;

            if (!string.IsNullOrEmpty(strProUserId))
            {
                if (!int.TryParse(strProUserId, out proUserId))
                {
                    Response.Redirect("~/UI/ProErrorGeneric.aspx");
                }
                tdComments.Visible = false;
                pnlComments.Visible = false;
                hfProUserId.Value = "&prouserid=" + proUserId.ToString();
            }

            try
            {
                service = new ServiceAPI();

                CanEdit = false;
                EditMode = false;
                EasyMode = false;

                ///////////////////////////
                // Check that the trail I is valid
                string strTrailId = Request.QueryString["trailid"];

                if (!int.TryParse(strTrailId, out trailId))
                {
                    Response.Redirect("~/UI/Home.aspx");
                }

                hfDeleteTrailUrl.Value = Page.ResolveUrl("~/UI/TrailDelete.aspx?trailid=" + trailId.ToString());

                if (trailId == 0 && currentSession == null)
                {
                    // It is not possible to create a trail without a session
                    Response.Redirect("~/UI/ErrorLoginFirst.aspx");
                }

                string strEasyMode = Request.QueryString["easymode"];
                if (!string.IsNullOrEmpty(strEasyMode))
                {
                    if (strEasyMode.ToLower() == "true")
                    {
                        EasyMode = true;
                    }
                }

                if (!Page.IsPostBack)
                {
                    if (!EasyMode)
                    {
                        currentTrail = LoadTrail();
                    }
                    else
                    {
                        log.Debug("Easy trails mode");

                        currentTrail = new fullTrail();
                        List<waypointWrapper> tmpList=new List<waypointWrapper>();
                        tmpList.Add(new waypointWrapper());
                        tmpList[0].waypoint = new waypoint();
                        tmpList[0].waypoint.latitude="0";
                        tmpList[0].waypoint.longitude="0";
                        tmpList[0].waypoint.name = "";
                        currentTrail.publicTrail = true;
                        currentTrail.created = DateTime.Now;
                        currentTrail.createdSpecified = true;
                        currentTrail.waypoints = tmpList.ToArray();
                        gmapTrails.LoadFullTrail(currentTrail);
                    }
                }
                else
                {
                    // We take the trail from the control
                    currentTrail = gmapTrails.CurrTrail[0];
                }

                ///////////////////////////
                // set the controls
                tblViewEditOptions.Visible = false;
                tdLoginToComment.Visible = currentSession == null;
                tdNewComment.Visible = currentSession != null;

                // Load layers
                List<string> layers = LoadLayers();

                sltLayers.Items.Clear();
                foreach(string s in layers)
                {
                    sltLayers.Items.Add(new ListItem(s, s));
                }

                if (currentSession != null)
                {
                    if (currentTrail.user == null)
                    {
                        userRequest ureq = new userRequest();
                        ureq.session = currentSession;
                        ureq.userId = currentSession.userId;
                        if (log.IsErrorEnabled) log.Debug("Calling: service.getUserDetails(ureq)");
                        userResponse uresp = ServiceHelper.HandleBintjeErrors(this, service.getUserDetails(ureq));
                        currentTrail.user = uresp.user;
                    }

                    if (currentTrail.user.id == currentSession.userId)
                    {
                        // This trail belongs to the user. Enable edit
                        CanEdit = true;
                    }
                }

                divEasyMode.Visible = false;

                string strEditMode = Request.QueryString["editmode"];
                if (!string.IsNullOrEmpty(strEditMode))
                {
                    if (strEditMode.ToLower() == "true")
                    {
                        if (!CanEdit)
                        {
                            Response.Redirect("~/UI/ErrorRights.aspx");
                        }
                        else
                        {
                            EditMode = true;
                            if (EasyMode)
                            {
                                divEasyMode.Visible = true;
                                tblTrailDetails.Visible = false;
                                divWaypointDetailsSelected.Visible = false;
                                txtWaypointDescription.Visible = false;
                            }
                        }
                    }
                }

                gmapTrails.CanEdit = EditMode;
                gmapTrails.EasyMode = EasyMode;

                tblCreateOptions.Visible = trailId == 0 && EditMode && !EasyMode;
                tblViewEditOptions.Visible = CanEdit && !EditMode && trailId != 0;
                tblEditOptions.Visible = EditMode && trailId != 0;

                lnkEasyTrail.HRef = ResolveUrl("~/UI/TrailDetails.aspx?trailId=" + trailId.ToString() + "&editmode=true&easymode=true");
                lnkEdit.HRef = ResolveUrl("~/UI/TrailDetails.aspx?trailId=" + trailId.ToString() + "&editmode=true");
                lnkView.HRef = ResolveUrl("~/UI/TrailDetails.aspx?trailId=" + trailId.ToString() + "&editmode=false");

                string imgUrl = null;

                if (currentTrail.imageUrl != null)
                    imgUrl = currentTrail.imageUrl.Replace("type=image","type=thumb");

                if (imgUrl == null &&
                    currentTrail != null &&
                    currentTrail.waypoints != null &&
                    currentTrail.waypoints.Length > 0 &&
                    currentTrail.waypoints[0].images != null &&
                    currentTrail.waypoints[0].images.Length > 0 &&
                    currentTrail.waypoints[0].images[0].url != null)
                {
                    imgUrl = currentTrail.waypoints[0].images[0].url;
                }

                lnkSimilarTrails.Visible = !EditMode;

//                if (imgUrl != null && !CanEdit)
                if (!CanEdit)
                {
                    try
                    {
//                        Uri tmpUri = new Uri(imgUrl.ToLower());
                        //NameValueCollection nvc = HttpUtility.ParseQueryString(tmpUri.Query);

                        //string imageid = nvc["id"];
                        //if (imageid != null)
                        //{
                        //    lnkSimilarTrails.HRef = ResolveClientUrl(@"~/ui/TrailSearch2.aspx?imageid=" + imageid + "&trailid=" + currentTrail.id);
                        //}
                    }
                    catch
                    {
                        // Do nothing
                    }
                }

                divEditTitle.Visible = EditMode;
                divEditRightDetails.Visible = EditMode;
                divViewTitle.Visible = !EditMode;
                divViewRightDetails.Visible = !EditMode;

                txtWaypointDescription.Visible = EditMode;
                lblWaypointDescription.Visible = !EditMode;

                divPicCommands.Visible = EditMode;

                UpdateComments();

                if (currentTrail != null)
                {
                    lblAuthor.Text = currentTrail.user.nickName;
                    lblTrailTitle.Text = currentTrail.title;
                    txtTrailTitle.Text = currentTrail.title;
                    lblTrailDescription.Text = currentTrail.description;
                    txtTrailDescription.Text = currentTrail.description;
                    chkIsPublic.Checked = currentTrail.publicTrail;

                    if (string.IsNullOrEmpty(lblTrailTitle.Text)) lblTrailTitle.Text = "No title";
                    if (string.IsNullOrEmpty(lblTrailDescription.Text)) lblTrailDescription.Text = "No description";

                    if (currentTrail.layers != null)
                    {
                        if (currentTrail.layers.Length > 0)
                        {
                            int i = 0;
                            for (; i < currentTrail.layers.Length - 1; i++)
                            {
                                lblTrailLayers.Text += currentTrail.layers[i] + ", ";
                            }
                            lblTrailLayers.Text += currentTrail.layers[i];

                            foreach(ListItem it in sltLayers.Items)
                            {
                                it.Selected=currentTrail.layers.Contains(it.Value);
                            }
                        }
                    }

                    if (currentTrail.imageUrl != null)
                    {
                        imgDetailsPicture.ImageUrl = currentTrail.imageUrl.Replace("type=image", "type=thumb");
                    }

                    lblTrailLenght.Text = string.Format("{0:0.00}", currentTrail.length);

                    if (currentTrail.waypoints != null)
                    {
                        lblTrailWaypointNumber.Text = currentTrail.waypoints.Length.ToString();
                    }
                    else
                    {
                        lblTrailWaypointNumber.Text = "0";
                    }

                    // TODO: should i get this info from the first waypoint?
                    if (currentTrail.waypoints != null && currentTrail.waypoints.Length > 0)
                    {
                        if (currentTrail.waypoints[0].waypoint != null)
                        {
                            lblTrailCountry.Text = currentTrail.waypoints[0].waypoint.country;
//                            txtTrailCountry.Text = currentTrail.waypoints[0].waypoint.country;
                            lblTrailCity.Text = currentTrail.waypoints[0].waypoint.city;
                            txtTrailCity.Text = currentTrail.waypoints[0].waypoint.city;

                            lblWaypointNumber.Text = "1";
                            lblWaypointTitle.Text = currentTrail.waypoints[0].waypoint.name;
                            lblWaypointDescription.Text = currentTrail.waypoints[0].waypoint.description;
                            txtWaypointDescription.Text = currentTrail.waypoints[0].waypoint.description;
                        }
                    }

                    if (!Page.IsPostBack)
                        txtDate.Text = currentTrail.created.ToString("MM/dd/yy");

                    if (currentTrail.created != null)
                        lblDate.Text = currentTrail.created.ToString("MM/dd/yy");

                }                
            }
            catch (ThreadAbortException) { }
            catch (Exception exc)
            {
                if (log.IsErrorEnabled)
                {
                    log.Error(exc.Source + " - " + exc.Message);
                }
                Response.Redirect("~/UI/ErrorGeneric.aspx");
            }
        }

        protected List<string> LoadLayers()
        {
            List<string> layers = new List<string>();
            if (log.IsErrorEnabled) log.Debug("Calling: service.getLayers()");
            layerSetResponse lresp = ServiceHelper.HandleBintjeErrors(this, service.getLayers());

            if (lresp != null)
            {
                foreach (string s in lresp.layers)
                {
                    layers.Add(s);
                }
            }

            return layers;
        }

        protected bintje.fullTrail LoadTrail()
        {
            trailRequest request = new trailRequest();
            request.trailId = trailId;
            request.session = currentSession;
            trailResponse response;

            // Load the trail or create an empty trail
            if (trailId != 0)
            {
                if (log.IsErrorEnabled) log.Debug("Calling: service.getTrailDetails(request)");
                response = ServiceHelper.HandleBintjeErrors(this, service.getTrailDetails(request));
                currentTrail = response.trail;
                gmapTrails.LoadFullTrail(currentTrail);

                return currentTrail;
            }
            else
            {
                currentTrail = new fullTrail();
                currentTrail.id = 0;
                currentTrail.publicTrail = true;
                userRequest ureq = new userRequest();
                ureq.session = currentSession;
                ureq.userId = currentSession.userId;
                if (log.IsErrorEnabled) log.Debug("Calling: service.getUserDetails(ureq)");
                userResponse uresp = ServiceHelper.HandleBintjeErrors(this, service.getUserDetails(ureq));
                currentTrail.user = uresp.user;

                return gmapTrails.CreateNewEmptyTrail();
            }
        }

        protected void UpdateComments()
        {
            tblComments.Visible = !EditMode;

            if (currentTrail != null)
            {
                if (currentTrail.annotations != null)
                {
                    lblTrailCommentsNumber.Text = currentTrail.annotations.Length.ToString();
                }
                else
                {
                    lblTrailCommentsNumber.Text = "0";
                }

                if (currentTrail.annotations != null)
                {
                    var sortedComments = (from c in currentTrail.annotations
                                          orderby c.created
                                          select c).ToArray();
                    lstComments.DataSource = sortedComments;
                }
                else
                {
                    lstComments.DataSource = null;
                }

            }
            else
            {
                //dtlComments.DataSource = null;
                lstComments.DataSource = null;
            }
            //            dtlComments.DataBind();
            lstComments.DataBind();
        }

        void replaceLocalFilenames(List<string> listFilesUrl)
        {
            if (currentTrail.waypoints != null)
            {
                foreach (bintje.waypointWrapper ww in currentTrail.waypoints)
                {
                    if (ww.images != null)
                    {
                        foreach (bintje.imageWrapper im in ww.images)
                        {
                            if (listFilesUrl.Contains(im.url))
                            {
                                string filename = Page.MapPath(im.url);
                                // The file must be resized and uploaded
                                System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(filename);
                                Bitmap tmpBmp = BitmapHelper.ResizeBitmap(bmp, 800, 600);
                                System.Drawing.ImageConverter converter = new System.Drawing.ImageConverter();
                                byte[] rawData = (byte[])converter.ConvertTo(bmp, typeof(byte[]));
                                im.imagedata = rawData;
                                im.url = "";
                                tmpBmp.Dispose();
                            }
                        }
                    }
                }
            }
        }

        protected void btnSubmit_Click(object sender, EventArgs e)
        {
            try
            {
                trailRequest request = new trailRequest();
                request.session = currentSession;
                request.trail = currentTrail;
                request.trailId = trailId;                          // this is new, isn't it?

                // Get bitmaps. resize and attach
                List<string> listFilesUrl = JSONHelper.Deserialize<List<string>>(hfUploadedFiles.Value);
                //
                trailResponse response;
                if (trailId == 0)
                {
                    int newTrailId = 0;
                    if (!EasyMode)
                    {
                        replaceLocalFilenames(listFilesUrl);

                        if (log.IsErrorEnabled) log.Debug("Calling: service.makeNewTrail(currentSession, currentTrail)");
                        response = ServiceHelper.HandleBintjeErrors(this, service.makeNewTrail(currentSession, currentTrail));
                        newTrailId = response.trailId;
                    }
                    else
                    {
                        if (currentTrail.waypoints.Length > 0)
                        {
                            // WE ARE IN EASY MODE - BATCH LOAD
                            if (log.IsErrorEnabled) log.Debug("Calling: service.createTrailFromImages(currentSession, imgRequest)");
                            imageRequest imgRequest = new imageRequest();

                            // Prepare the image request
                            imgRequest.latitude = currentTrail.waypoints[0].waypoint.latitude;
                            imgRequest.longitude = currentTrail.waypoints[0].waypoint.longitude;
                            imgRequest.layers = currentTrail.layers;
                            imgRequest.session = currentSession;
                            imgRequest.traildescription = currentTrail.description;
                            imgRequest.trailtitle = currentTrail.title;

                            List<byte[]> imageData = new List<byte[]>();

                            if (currentTrail.waypoints != null)
                            {
                                foreach (bintje.waypointWrapper ww in currentTrail.waypoints)
                                {
                                    if (ww.images != null)
                                    {
                                        foreach (bintje.imageWrapper im in ww.images)
                                        {
                                            if (listFilesUrl.Contains(im.url))
                                            {
                                                string filename = Page.MapPath(im.url);
                                                // The file must be resized and uploaded
                                                System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(filename);
                                                Bitmap tmpBmp = BitmapHelper.ResizeBitmap(bmp, 800, 600);
                                                System.Drawing.ImageConverter converter = new System.Drawing.ImageConverter();
                                                byte[] rawData = (byte[])converter.ConvertTo(bmp, typeof(byte[]));
                                                imageData.Add(rawData);
                                                tmpBmp.Dispose();
                                            }
                                        }
                                    }
                                }
                            }

                            imgRequest.imagedata = imageData.ToArray();

                            response = ServiceHelper.HandleBintjeErrors(this, service.createTrailFromImages(currentSession, imgRequest));
                            newTrailId = response.trailId;
                        }
                    }

                    if (newTrailId != 0)
                    {
                        // We should now redirect to an edit page
                        Response.Redirect(ResolveUrl("~/UI/TrailDetails.aspx?trailId=" + newTrailId.ToString() + "&editmode=true"));
                    }
                }
                else
                {
                    replaceLocalFilenames(listFilesUrl);

                    request.trail.created = DateTime.Parse(txtDate.Text);
                    if (log.IsErrorEnabled) log.Debug("Calling: service.editTrailData(request)");

                    // The new version complains if annotations is not empty..
                    request.trail.annotations = null;

                    response = ServiceHelper.HandleBintjeErrors(this, service.editTrailData(request));

                    Response.Redirect(ResolveUrl("~/UI/TrailDetails.aspx?trailId=" + request.trail.id.ToString() + "&editmode=true"));
                }
            }
            catch (ThreadAbortException) {}
            catch (Exception exc)
            {
                if (log.IsErrorEnabled)
                {
                    log.Error(exc.Source + " - " + exc.Message);
                }
                Response.Redirect("~/UI/ErrorGeneric.aspx");
            }
        }

        protected void btnSendComment_Click(object sender, EventArgs e)
        {
            userRequest ureq = new userRequest();
            ureq.session = currentSession;
            ureq.userId = currentSession.userId;
            if (log.IsErrorEnabled) log.Debug("Calling: service.getUserDetails(ureq)");
            userResponse uresp = ServiceHelper.HandleBintjeErrors(this, service.getUserDetails(ureq));

            string newComment = txtComment.Text;
            string newCommentName = uresp.user.nickName;

            try
            {
                ///////////////////////////
                // Load the trail 
                commentRequest request = new commentRequest();
                request.annotation = new annotation();
                request.annotation.comment = newComment;
                request.annotation.name = newCommentName;
                request.annotation.created = DateTime.Now.ToBinary();
                request.session = currentSession;

                ///////////////////////////
                // Check that the trail I is valid
                string strTrailId = Request.QueryString["trailid"];
                int trailId;

                if (int.TryParse(strTrailId, out trailId))
                {
                    request.trailid = trailId;
                    if (log.IsErrorEnabled) log.Debug("Calling: service.addComment(request)");
                    contactResponse response = ServiceHelper.HandleBintjeErrors(this, service.addComment(request));
                }

                LoadTrail();
                UpdateComments();
            }
            catch (Exception exc)
            {
                if (log.IsErrorEnabled)
                {
                    log.Error(exc.Source + " - " + exc.Message);
                }
                Response.Redirect("~/UI/ErrorGeneric.aspx");
            }
        }

        protected void lstComments_PagePropertiesChanged(object sender, EventArgs e)
        {
            lstComments.DataBind();
        }
    }
}
